/*

Boost Software License - Version 1.0 - August 17th, 2003

Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

*/
module derelict.devil.ilut;

private
{
    import derelict.util.loader;
    import derelict.util.system;
    import derelict.devil.types;

    static if(Derelict_OS_Windows)
        enum libNames = "ilut.dll";
    else static if (Derelict_OS_Mac)
        enum libNames = "libILUT.dylib";
    else static if(Derelict_OS_Posix)
        enum libNames = "libILUT.so";
    else
        static assert(0, "Need to implement ILUT libNames for this operating system.");
}

enum : ILenum
{
    ILUT_VERSION_1_7_3=1,
    ILUT_VERSION=173,

    ILUT_OPENGL_BIT=0x00000001,
    ILUT_D3D_BIT=0x00000002,
    ILUT_ALL_ATTRIB_BITS=0x000FFFFF,

    ILUT_INVALID_ENUM=0x0501,
    ILUT_OUT_OF_MEMORY=0x0502,
    ILUT_INVALID_VALUE=0x0505,
    ILUT_ILLEGAL_OPERATION=0x0506,
    ILUT_INVALID_PARAM=0x0509,
    ILUT_COULD_NOT_OPEN_FILE=0x050A,
    ILUT_STACK_OVERFLOW=0x050E,
    ILUT_STACK_UNDERFLOW=0x050F,
    ILUT_BAD_DIMENSIONS=0x0511,
    ILUT_NOT_SUPPORTED=0x0550,

    ILUT_PALETTE_MODE=0x0600,
    ILUT_OPENGL_CONV=0x0610,
    ILUT_D3D_MIPLEVELS=0x0620,
    ILUT_MAXTEX_WIDTH=0x0630,
    ILUT_MAXTEX_HEIGHT=0x0631,
    ILUT_MAXTEX_DEPTH=0x0632,
    ILUT_GL_USE_S3TC=0x0634,
    ILUT_D3D_USE_DXTC=0x0634,
    ILUT_GL_GEN_S3TC=0x0635,
    ILUT_D3D_GEN_DXTC=0x0635,
    ILUT_S3TC_FORMAT=0x0705,
    ILUT_DXTC_FORMAT=0x0705,
    ILUT_D3D_POOL=0x0706,
    ILUT_D3D_ALPHA_KEY_COLOR=0x0707,
    ILUT_D3D_ALPHA_KEY_COLOUR=0x0707,
    ILUT_FORCE_INTEGER_FORMAT=0x0636,

    ILUT_GL_AUTODETECT_TEXTURE_TARGET=0x0807,

    ILUT_VERSION_NUM=IL_VERSION_NUM,
    ILUT_VENDOR=IL_VENDOR,

    ILUT_OPENGL=0,
    ILUT_ALLEGRO=1,
    ILUT_WIN32=2,
    ILUT_DIRECT3D8=3,
    ILUT_DIRECT3D9=4,
    ILUT_X11=5,
}

extern(System)
{
    alias nothrow ILboolean function(ILenum) da_ilutDisable;
    alias nothrow ILboolean function(ILenum) da_ilutEnable;
    alias nothrow ILboolean function(ILenum) da_ilutGetBoolean;
    alias nothrow ILvoid function(ILenum, ILboolean*) da_ilutGetBooleanv;
    alias nothrow ILint function(ILenum) da_ilutGetInteger;
    alias nothrow ILvoid function(ILenum, ILint*) da_ilutGetIntegerv;
    alias nothrow ILstring function(ILenum) da_ilutGetString;
    alias nothrow ILvoid function() da_ilutInit;
    alias nothrow ILboolean function(ILenum) da_ilutIsDisabled;
    alias nothrow ILboolean function(ILenum) da_ilutIsEnabled;
    alias nothrow ILvoid function() da_ilutPopAttrib;
    alias nothrow ILvoid function(ILuint) da_ilutPushAttrib;
    alias nothrow ILvoid function(ILenum, ILint) da_ilutSetInteger;
    alias nothrow ILboolean function(ILenum) da_ilutRenderer;
    alias nothrow uint function() da_ilutGLBindTexImage;
    alias nothrow uint function() da_ilutGLBindMipmaps;
    alias nothrow ILboolean function() da_ilutGLBuildMipmaps;
    alias nothrow uint function(ILstring FileName) da_ilutGLLoadImage;
    alias nothrow ILboolean function() da_ilutGLScreen;
    alias nothrow ILboolean function() da_ilutGLScreenie;
    alias nothrow ILboolean function(ILstring, uint) da_ilutGLSaveImage;
    alias nothrow ILboolean function(uint) da_ilutGLSetTex;
    alias nothrow ILboolean function(uint) da_ilutGLTexImage;
    alias nothrow ILboolean function(uint, ILuint, ILuint) da_ilutGLSubTex;

    version(Windows)
    {
        private import derelict.util.wintypes;
        alias nothrow HBITMAP function(HDC hDC) da_ilutConvertToHBitmap;
        alias nothrow ILvoid function(ILubyte *Data) da_ilutFreePaddedData;
        alias nothrow ILvoid function(BITMAPINFO *Info) da_ilutGetBmpInfo;
        alias nothrow HPALETTE function() da_ilutGetHPal;
        alias nothrow ILubyte* function() da_ilutGetPaddedData;
        alias nothrow ILboolean function() da_ilutGetWinClipboard;
        alias nothrow ILboolean function(HINSTANCE hInst, ILint ID,  ILstring ResourceType, ILenum Type) da_ilutLoadResource;
        alias nothrow ILboolean function(HBITMAP Bitmap) da_ilutSetHBitmap;
        alias nothrow ILboolean function(HPALETTE Pal) da_ilutSetHPal;
        alias nothrow ILboolean function() da_ilutSetWinClipboard;
        alias nothrow HBITMAP function( ILstring FileName, HDC hDC) da_ilutWinLoadImage;
        alias nothrow ILboolean function( ILstring Url) da_ilutWinLoadUrl;
        alias nothrow ILboolean function(ILuint XPos, ILuint YPos, ILuint Width, ILuint Height, HDC hDC) da_ilutWinPrint;
        alias nothrow ILboolean function( ILstring FileName, HBITMAP Bitmap) da_ilutWinSaveImage;
    }

    version(Linux)
    {
        // TODO
    }
}

__gshared
{
    da_ilutDisable ilutDisable;
    da_ilutEnable ilutEnable;
    da_ilutGetBoolean ilutGetBoolean;
    da_ilutGetBooleanv ilutGetBooleanv;
    da_ilutGetInteger ilutGetInteger;
    da_ilutGetIntegerv ilutGetIntegerv;
    da_ilutGetString ilutGetString;
    da_ilutInit ilutInit;
    da_ilutIsDisabled ilutIsDisabled;
    da_ilutIsEnabled ilutIsEnabled;
    da_ilutPopAttrib ilutPopAttrib;
    da_ilutPushAttrib ilutPushAttrib;
    da_ilutSetInteger ilutSetInteger;
    da_ilutRenderer ilutRenderer;
    da_ilutGLBindTexImage ilutGLBindTexImage;
    da_ilutGLBindMipmaps ilutGLBindMipmaps;
    da_ilutGLBuildMipmaps ilutGLBuildMipmaps;
    da_ilutGLLoadImage ilutGLLoadImage;
    da_ilutGLScreen ilutGLScreen;
    da_ilutGLScreenie ilutGLScreenie;
    da_ilutGLSaveImage ilutGLSaveImage;
    da_ilutGLSetTex ilutGLSetTex;
    da_ilutGLTexImage ilutGLTexImage;
    da_ilutGLSubTex ilutGLSubTex;

    version(Windows)
    {
        da_ilutConvertToHBitmap ilutConvertToHBitmap;
        da_ilutFreePaddedData ilutFreePaddedData;
        da_ilutGetBmpInfo ilutGetBmpInfo;
        da_ilutGetHPal ilutGetHPal;
        da_ilutGetPaddedData ilutGetPaddedData;
        da_ilutGetWinClipboard ilutGetWinClipboard;
        da_ilutLoadResource ilutLoadResource;
        da_ilutSetHBitmap ilutSetHBitmap;
        da_ilutSetHPal ilutSetHPal;
        da_ilutSetWinClipboard ilutSetWinClipboard;
        da_ilutWinLoadImage ilutWinLoadImage;
        da_ilutWinLoadUrl ilutWinLoadUrl;
        da_ilutWinPrint ilutWinPrint;
        da_ilutWinSaveImage ilutWinSaveImage;
    }
}

class DerelictILUTLoader : SharedLibLoader
{

    protected
    {
        override void loadSymbols()
        {
            bindFunc(cast(void**)&ilutDisable, "ilutDisable");
            bindFunc(cast(void**)&ilutEnable, "ilutEnable");
            bindFunc(cast(void**)&ilutGetBoolean, "ilutGetBoolean");
            bindFunc(cast(void**)&ilutGetBooleanv, "ilutGetBooleanv");
            bindFunc(cast(void**)&ilutGetInteger, "ilutGetInteger");
            bindFunc(cast(void**)&ilutGetIntegerv, "ilutGetIntegerv");
            bindFunc(cast(void**)&ilutGetString, "ilutGetString");
            bindFunc(cast(void**)&ilutInit, "ilutInit");
            bindFunc(cast(void**)&ilutIsDisabled, "ilutIsDisabled");
            bindFunc(cast(void**)&ilutIsEnabled, "ilutIsEnabled");
            bindFunc(cast(void**)&ilutPopAttrib, "ilutPopAttrib");
            bindFunc(cast(void**)&ilutPushAttrib, "ilutPushAttrib");
            bindFunc(cast(void**)&ilutSetInteger, "ilutSetInteger");
            bindFunc(cast(void**)&ilutRenderer, "ilutRenderer");
            bindFunc(cast(void**)&ilutGLBindTexImage, "ilutGLBindTexImage");
            bindFunc(cast(void**)&ilutGLBindMipmaps, "ilutGLBindMipmaps");
            bindFunc(cast(void**)&ilutGLBuildMipmaps, "ilutGLBuildMipmaps");
            bindFunc(cast(void**)&ilutGLLoadImage, "ilutGLLoadImage");
            bindFunc(cast(void**)&ilutGLScreen, "ilutGLScreen");
            bindFunc(cast(void**)&ilutGLScreenie, "ilutGLScreenie");
            bindFunc(cast(void**)&ilutGLSaveImage, "ilutGLSaveImage");
            bindFunc(cast(void**)&ilutGLSetTex, "ilutGLSetTex");
            bindFunc(cast(void**)&ilutGLTexImage, "ilutGLTexImage");
            bindFunc(cast(void**)&ilutGLSubTex, "ilutGLSubTex");

            version(Windows)
            {
                bindFunc(cast(void**)&ilutConvertToHBitmap, "ilutConvertToHBitmap");
                bindFunc(cast(void**)&ilutFreePaddedData, "ilutFreePaddedData");
                bindFunc(cast(void**)&ilutGetBmpInfo, "ilutGetBmpInfo");
                bindFunc(cast(void**)&ilutGetHPal, "ilutGetHPal");
                bindFunc(cast(void**)&ilutGetPaddedData, "ilutGetPaddedData");
                bindFunc(cast(void**)&ilutGetWinClipboard, "ilutGetWinClipboard");
                bindFunc(cast(void**)&ilutLoadResource, "ilutLoadResource");
                bindFunc(cast(void**)&ilutSetHBitmap, "ilutSetHBitmap");
                bindFunc(cast(void**)&ilutSetHPal, "ilutSetHPal");
                bindFunc(cast(void**)&ilutSetWinClipboard, "ilutSetWinClipboard");
                bindFunc(cast(void**)&ilutWinLoadImage, "ilutWinLoadImage");
                bindFunc(cast(void**)&ilutWinLoadUrl, "ilutWinLoadUrl");
                bindFunc(cast(void**)&ilutWinPrint, "ilutWinPrint");
                bindFunc(cast(void**)&ilutWinSaveImage, "ilutWinSaveImage");
            }

            version(linux)
            {
               // TODO
            }
        }
    }

    public
    {
        this()
        {
            super(libNames);
        }
    }
}

__gshared DerelictILUTLoader DerelictILUT;

shared static this()
{
    DerelictILUT = new DerelictILUTLoader();
}

shared static ~this()
{
    DerelictILUT.unload();
}
